//
// Created by F1997 on 2024/10/17.
//

#ifndef NETWORK_TRAFFIC_PROCESSING_PCH_H
#define NETWORK_TRAFFIC_PROCESSING_PCH_H

// 预编译头文件，可以防止头文件重复导入，且统一管理不同平台特有的头文件
// ===================================================================== 头文件
// TODO:使用的内库
// c 的

// c++ 的
#include <string>
#include <chrono>
#include <iostream>
#include <sstream>
#include <time.h>
#include <iomanip> // 科学计数法转换，注意包含这个头文件
#include <fstream>
#include <filesystem>
#include <cstring>
#include <regex>
#include <algorithm>
#include <memory>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <map>
#include <unordered_map>
#include <stdio.h>


#ifdef _WIN32
// windows 特有的内库
#include <windows.h>
#include <direct.h>
#else
// linux 特有的内库
#include <unistd.h> // linux下加入的应用
#include <fcntl.h>
#include <iconv.h>
#include <future>
#include <thread>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#include <sys/wait.h>
//#include <bits/mqueue.h> // 需要添加动态库
#include <future>
//#include <atomic> // 原子操作
#include <stdlib.h>
#include <unistd.h> //

#include <netinet/ether.h>  // For ether_header
#include <netinet/ip.h>     // For IP headers
#include <netinet/tcp.h>    // For TCP headers
#include <netinet/udp.h>    // For UDP headers
#include <arpa/inet.h>      // For inet_ntoa, etc.

#endif

// TODO:特定项目使用的第三方库
#include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/async.h"
#include "pcap.h"

#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/if_ether.h>  // 包含 ETHERTYPE_IP 的定义
#include <arpa/inet.h> // 用于 inet_ntoa


#include "tins/tins.h"


// ===================================================================== 数据类型
// TODO:跨平台数据类型
#ifdef _WIN32
// windows 特有的
#define PATH_CHAR_T wchar_t
#define PATH_TEXT(x) L##x
#else
// linux 特有的
#define PATH_CHAR_T char
#define PATH_TEXT(x) x
#endif

// 共有的
#define CONST               const
#define VOID void
typedef char CHAR;
typedef short SHORT;
typedef long LONG;
typedef int                 INT;
typedef unsigned int        UINT;
typedef unsigned long       DWORD;
typedef int                 BOOL;
typedef unsigned char       BYTE;
typedef unsigned short      WORD;
typedef CHAR* PCHAR, * LPCH, * PCH;
typedef BYTE  BOOLEAN;
typedef CONST CHAR* LPCCH, * PCCH;
typedef CONST CHAR* LPCSTR, * PCSTR;
typedef wchar_t WCHAR;    // wc,   16-bit UNICODE character
typedef WCHAR* PWCHAR, * LPWCH, * PWCH;
typedef CONST WCHAR* LPCWCH, * PCWCH;
typedef WCHAR* NWPSTR, * LPWSTR, * PWSTR;
typedef void* PVOID;
typedef unsigned long ULONG;
typedef ULONG* PULONG;
typedef unsigned short USHORT;
typedef USHORT* PUSHORT;
typedef unsigned char UCHAR;
typedef UCHAR* PUCHAR;
typedef void* HANDLE;
typedef BYTE* PBYTE;
typedef long NTSTATUS, * PNTSTATUS;
typedef size_t LONG_PTR;
typedef size_t ULONG_PTR, * PULONG_PTR;
typedef ULONG_PTR DWORD_PTR, * PDWORD_PTR;
typedef CONST WCHAR* LPCWSTR, * PCWSTR;
typedef CHAR* NPSTR, * LPSTR, * PSTR;
typedef BOOL * LPBOOL;


#ifndef NULL
#define NULL 0
#endif

#define MAX_PATH                                            260

#define FALSE               0
#define TRUE                1

#define CP_ACP                    0           // default to ANSI code page
#define CP_OEMCP                  1           // default to OEM  code page
#define CP_MACCP                  2           // default to MAC  code page
#define CP_THREAD_ACP             3           // current thread's ANSI code page
#define CP_SYMBOL                 42          // SYMBOL translations
#define CP_UTF7                   65000       // UTF-7 translation
#define CP_UTF8                   65001       // UTF-8 translation

#define MB_PRECOMPOSED            0x00000001  // DEPRECATED: use single precomposed characters when possible.
#define MB_COMPOSITE              0x00000002  // DEPRECATED: use multiple discrete characters when possible.
#define MB_USEGLYPHCHARS          0x00000004  // DEPRECATED: use glyph chars, not ctrl chars
#define MB_ERR_INVALID_CHARS      0x00000008  // error for invalid chars

#define WC_COMPOSITECHECK         0x00000200  // convert composite to precomposed
#define WC_DISCARDNS              0x00000010  // discard non-spacing chars          // Used with WC_COMPOSITECHECK
#define WC_SEPCHARS               0x00000020  // generate separate chars            // Used with WC_COMPOSITECHECK
#define WC_DEFAULTCHAR            0x00000040  // replace w/ default char            // Used with WC_COMPOSITECHECK
#define WC_ERR_INVALID_CHARS      0x00000080  // error for invalid chars
#define WC_NO_BEST_FIT_CHARS      0x00000400  // do not use best fit chars

#define ERROR_INVALID_FLAGS              1004L
#define ERROR_INSUFFICIENT_BUFFER        122L    // dderror
#define ERROR_INVALID_PARAMETER          87L    // dderror
#define ERROR_NO_UNICODE_TRANSLATION     1113L



// ===================================================================== 业务无关的静态工具函数
// 停止文件是否存在
static inline bool isStopFileExist(const std::string& stop_file_path){
    std::filesystem::path stopAbsolutePath = std::filesystem::absolute(stop_file_path); // 相对路径转绝对路径
    if (access(stopAbsolutePath.c_str(), 0) == -1) {  // access=确定文件是否存在或者判断读写执行权限
        // 文件不存在，返回false
        return false;
    }
    else {
        return true;
    }
}

// 按空格分割字符串
static inline std::vector<std::string> splitBySpace(const std::string& str) {
    std::istringstream iss(str);
    std::vector<std::string> tokens;
    std::string token;

    while (iss >> token) {
        tokens.push_back(token);
    }

    return tokens;
}

// 按 特殊字符 分割字符串
static inline std::vector<std::string> splitByDelimiter(const std::string& str, char delimiter) {
    std::istringstream iss(str);
    std::vector<std::string> tokens;
    std::string token;

    while (std::getline(iss, token, delimiter)) {
        tokens.push_back(token);
    }

    return tokens;
}

// 删除 string 的左空格
static inline void ltrim(std::string &str)
{
    str.erase(0, str.find_first_not_of(' '));
}

// 删除string 的右空格
static inline void rtrim(std::string &str)
{
    size_t n = str.find_last_not_of('\0');
    size_t str_size = str.size();
    if (n != std::string::npos) {
        str.erase(n + 1, str_size - n);
    }

    n = str.find_last_not_of(' ');
    if (n != std::string::npos) {
        str.erase(n + 1, str_size - n);
    }
}

// 去除两边的空格
static inline void trim(std::string &str)
{
    str.erase(0, str.find_first_not_of(' '));

    size_t n = str.find_last_not_of('\0');
    size_t str_size = str.size();
    if (n != std::string::npos) {
        str.erase(n + 1, str_size - n);
    }

    n = str.find_last_not_of(' ');
    if (n != std::string::npos) {
        str.erase(n + 1, str_size - n);
    }
}

// 获取当前时间
// 返回值样例：20241108 09:16:35
static inline std::string currTime()
{
    char current_time[70];
    time_t tt = time(NULL);
    struct tm *t = localtime(&tt);
    sprintf(current_time, "%04d%02d%02d %02d:%02d:%02d", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
    return current_time;
}

// str转int，n进制转十进制？
static inline int str_int(const std::string& str_in)
{
    if (str_in == "" || str_in.length() == 0) {
        return 0;
    }
    return stoi(str_in);
}

// str转double，科学计数法的不能转
static inline double str_double(const std::string& str_in)
{
    if (str_in == "" || str_in.length() == 0) {
        return 0;
    }
    if (str_in.find("E+") != std::string::npos || str_in.find("E-") != std::string::npos) {
        return 0;
    }
    return stod(str_in);
}

// double值和科学计数法之间进行转换，double值校验
static inline double sanitize_double(double value)
{
    if (value > -1e100 && value < 1e100) return value;
    else return 0.0;
}

//
static inline uint16_t read_uint16(uint8_t* buf)
{
    uint8_t* tbuf = (uint8_t*)buf;
    return (tbuf[0] << 8) + tbuf[1];
}

//
static inline uint32_t read_uint32(uint8_t* buf)
{
    uint8_t* tbuf = (uint8_t*)buf;
    return (tbuf[0] << 24) + (tbuf[1] << 16) + (tbuf[2] << 8) + tbuf[3];
}

// 时间戳格式化
static inline std::string Stamp2Time(long long timestamp)
{
    time_t tick = (time_t)(timestamp);//转换时间
    struct tm tm;
    char s[256];
    tm = *localtime(&tick);
    strftime(s, sizeof(s), "%H%M%S", &tm); //%Y-%m-%d  %Y%m%d
    return s;
}



#endif //NETWORK_TRAFFIC_PROCESSING_PCH_H
